home *** CD-ROM | disk | FTP | other *** search
/ Computer Select (Limited Edition) / Computer Select.iso / dobbs / v16n08 / vogel.exe / LISTINGS < prev    next >
Encoding:
Text File  |  1991-04-01  |  30.7 KB  |  1,488 lines

  1.  
  2. Here is a listing of the source code for the "new" program.  The method I
  3. used to handle token replacement won't win the Turing prize for elegance, but
  4. it gets the job done.
  5.  
  6. ==============================================================================
  7.  
  8.             Listing 1.  File "new.h"
  9.  
  10. #ifndef    lint
  11. static char    *new_h_rcsid =
  12. "$Header: new.h,v 1.5 91/03/29 19:23:08 vogel Exp $";
  13.  
  14. static char    *new_h_source =
  15. "$Source: /d/cdc/vogel/source/new/RCS/new.h,v $";
  16.  
  17. #endif
  18.  
  19. /*
  20.  * NAME:
  21.  *    new.h
  22.  *
  23.  * SYNOPSIS:
  24.  *    #include "new.h"
  25.  *
  26.  * DESCRIPTION:
  27.  *    Holds the data structure for the command line options, plus
  28.  *    general definitions.
  29.  *    
  30.  * AUTHOR:
  31.  *    Karl Vogel
  32.  *
  33.  * BUGS:
  34.  *    None noticed.
  35.  *
  36.  * REVISIONS:
  37.  *
  38.  * $Log:    new.h,v $
  39.  * Revision 1.5  91/03/29  19:23:08  vogel
  40.  * 1.  Renamed the directory holding the templates.
  41.  * 
  42.  * Revision 1.4  91/03/15  16:56:33  vogel
  43.  * 1.  Ran indent on the code and reformatted the comment header.
  44.  * 
  45.  * Revision 1.3  90/07/03  14:21:20  vogel
  46.  * 1.  Added a new field:  extension of the program to be created.  This is also
  47.  *     in "macro.h", but it can be most easily set from examining the command
  48.  *     line options.
  49.  * 
  50.  * Revision 1.2  90/07/03  12:07:06  vogel
  51.  * 1.  Added a flag to the OPTIONS structure which is TRUE if the created file
  52.  *     is to be edited, FALSE otherwise.
  53.  * 
  54.  * Revision 1.1  90/06/29  15:32:04  vogel
  55.  * Initial revision
  56.  * 
  57.  */
  58.  
  59. #include    <stdio.h>
  60.  
  61. #define        YES        1
  62. #define        NO        0
  63.  
  64. /*
  65.  *    Error codes.
  66.  */
  67.  
  68. #define        OK        0
  69. #define        EMALLOC        1
  70.  
  71. /*
  72.  *    Set the directory holding the templates, and the prefix of each
  73.  *    template file.
  74.  */
  75.  
  76. #define        DIRECTORY    "/d/cdc/vogel/source/new/"
  77. #define        PREFIX        "template."
  78.  
  79. /*
  80.  *    Set up the options structure.
  81.  */
  82.  
  83. struct options_data
  84. {
  85.     char          **files;        /* NULL-terminated array of C files
  86.                      * to be created. */
  87.  
  88.     char           *template;    /* Full name of the desired   
  89.                      * template file. */
  90.  
  91.     char            exten[5];    /* Extension of the program to be
  92.                      * created.  */
  93.  
  94.     int             edit;        /* True if the created program is to
  95.                      * be edited. */
  96.  
  97.     int             help;        /* True if help is needed. */
  98. };
  99.  
  100. typedef struct options_data OPTIONS;
  101.  
  102. ==============================================================================
  103.  
  104.             Listing 2.  File "macro.h"
  105.  
  106. #ifndef    lint
  107. static char    *macro_h_rcsid =
  108. "$Header: macro.h,v 1.2 91/03/15 16:56:28 vogel Exp $";
  109.  
  110. static char    *macro_h_source =
  111. "$Source: /d/cdc/vogel/source/new/RCS/macro.h,v $";
  112.  
  113. #endif
  114.  
  115. /*
  116.  * NAME:
  117.  *    macro.h
  118.  *
  119.  * SYNOPSIS:
  120.  *    #include "macro.h"
  121.  *
  122.  * DESCRIPTION:
  123.  *    Header file for macro substitutions.
  124.  *    
  125.  * AUTHOR:
  126.  *    Karl Vogel
  127.  *
  128.  * BUGS:
  129.  *    Any problems or suggestions. 
  130.  *
  131.  * REVISIONS:
  132.  *
  133.  * $Log:    macro.h,v $
  134.  * Revision 1.2  91/03/15  16:56:28  vogel
  135.  * 1.  Ran indent on the code and reformatted the comment header.
  136.  * 
  137.  * Revision 1.1  90/06/29  17:40:15  vogel
  138.  * Initial revision
  139.  * 
  140.  */
  141.  
  142. #define        BUFFER        512
  143.  
  144. struct macro_data
  145. {
  146.     char            args[BUFFER];    /* Arguments for the function: full
  147.                      * declarations separated by
  148.                      * semicolons and newlines. Replaces
  149.                      * $a in a template.  */
  150.  
  151.     char            body[BUFFER];    /* Body of the function.  Comes under
  152.                      * the first comment after the
  153.                      * variable declarations. Includes
  154.                      * tabs and newlines. Replaces $b in
  155.                      * a template.  */
  156.  
  157.     char            exten[5];    /* Extension of the created file,
  158.                      * usually ".c".  Replaces $e in a
  159.                      * template. */
  160.  
  161.     char            functions[BUFFER];    /* Internal function
  162.                          * declarations. Comes just
  163.                          * after the start of the
  164.                          * function itself.  Includes
  165.                          * tabs and newlines. 
  166.                          * Replaces $f in a template. */
  167.  
  168.     char            globals[BUFFER];/* External global variables. Comes
  169.                      * just before the start of the
  170.                      * function itself.  Includes tabs
  171.                      * and newlines.  Replaces $g in a
  172.                      * template. */
  173.  
  174.     char            include[BUFFER];/* External include files.  Comes
  175.                      * just before the start of the
  176.                      * function itself.  Includes tabs
  177.                      * and newlines.  Replaces $i in a
  178.                      * template.  */
  179.  
  180.     char            alist[BUFFER];    /* Short form of the argument list,
  181.                      * consisting of just the variable
  182.                      * names separated by commas. 
  183.                      * Replaces $l in a template. */
  184.  
  185.     char            name[64];    /* Name of the function being
  186.                      * created.  May or may not be the
  187.                      * same as the filename. Replaces $n
  188.                      * in a template.  */
  189.  
  190.     char            define[BUFFER];    /* Holds preprocessor #define
  191.                      * statements separated by newlines. 
  192.                      * Replaces $p in a template. */
  193.  
  194.     char            rev[16];    /* Current revision level of the
  195.                      * created function.  Replaces $r in
  196.                      * a template. */
  197.  
  198.     char            type[32];    /* Type of function created, i.e.
  199.                      * char * or int.  Replaces $t in a
  200.                      * template.  */
  201.  
  202.     char            usage[BUFFER];    /* Comes right after the first use of
  203.                      * the function name, and tells you
  204.                      * what the function is supposed to
  205.                      * do.  Just above the Usage section
  206.                      * in the intro comments.  This is
  207.                      * the only "smart" macro: won't let
  208.                      * you put too many words on a line,
  209.                      * and starts each line with a
  210.                      * comment indicator.  Replaces $u in
  211.                      * a template. */
  212.  
  213.     char            vars[BUFFER];    /* Holds internally-declared
  214.                      * variables, separated by tabs,
  215.                      * semicolons, and newlines. Replaces
  216.                      * $v in a template.  */
  217.  
  218.     char            userid[16];    /* Holds the author's userid.
  219.                      * Replaces $w in a template.  */
  220.  
  221.     char            username[BUFFER];    /* Holds the author's full
  222.                          * name. Replaces $x in a
  223.                          * template.  */
  224.  
  225.     char            token;        /* Holds the character to be used as
  226.                      * a token indicator.  Shown as a
  227.                      * dollar sign in this file.  */
  228.  
  229.     int             year;        /* Current year.  Replaces $y in a
  230.                      * template. */
  231.  
  232.     int             month;        /* Current month.  Replaces $c in a
  233.                      * template. */
  234.  
  235.     int             day;        /* Current day.  Replaces $d in a
  236.                      * template. */
  237.  
  238.     int             hour;        /* Current hour.  Replaces $h in a
  239.                      * template. */
  240.  
  241.     int             minute;        /* Current minute.  Replaces $m in a
  242.                      * template.  */
  243.  
  244.     int             second;        /* Current second.  Replaces $s in a
  245.                      * template.  */
  246. };
  247.  
  248. typedef struct macro_data MACRO;
  249.  
  250. ==============================================================================
  251.  
  252.             Listing 3.  File "new.c"
  253.  
  254. #ifndef    lint
  255. static char    *new_c_rcsid =
  256. "$Header: new.c,v 1.6 91/03/15 16:55:42 vogel Exp $";
  257.  
  258. static char    *new_c_source =
  259. "$Source: /d/cdc/vogel/source/new/RCS/new.c,v $";
  260.  
  261. #endif
  262.  
  263. /*
  264.  * NAME:
  265.  *    new
  266.  *
  267.  * SYNOPSIS:
  268.  *    new [-c] [-h] [-mx] file [file ...]
  269.  *
  270.  * DESCRIPTION:
  271.  *    Creates and optionally edits one or more new C programs.
  272.  *
  273.  *    "new" makes extensive use of templates to create new C files.
  274.  *    A template file has the name "template.x", where 'x' is the string
  275.  *    which follows '-m' in the program arguments.
  276.  *
  277.  *    You can create other templates by adding template files to the
  278.  *    template directory specified in the header file "new.h".
  279.  *    
  280.  * OPTIONS:
  281.  *    "-c"    creates a new program but does NOT edit it.
  282.  *
  283.  *    "-h"    prints help information if improper or no arguments at all
  284.  *        are given.
  285.  *
  286.  *    "-mx"    creates a program of type 'x', where x is one of the following:
  287.  *        d - function driver.
  288.  *        f - normal function (default).
  289.  *        h - header file.
  290.  *        i - program to handle simple I/O.
  291.  *        m - main routine with arguments.
  292.  *        o - function to handle command line arguments.
  293.  *        s - stub (placeholder) function.
  294.  *
  295.  *    "file"    is one or more C files to be created.  A suffix of ".c" will
  296.  *        be appended if it isn't there already.  If the file already
  297.  *        exists, you will be asked if you want to overwrite it.
  298.  *
  299.  * AUTHOR:
  300.  *    Karl Vogel
  301.  *
  302.  * BUGS:
  303.  *    None noticed.
  304.  *
  305.  * REVISIONS:
  306.  *
  307.  * $Log:    new.c,v $
  308.  * Revision 1.6  91/03/15  16:55:42  vogel
  309.  * 1.  Ran indent on the code and reformatted the comment header.
  310.  * 
  311.  * Revision 1.5  90/09/24  16:42:03  vogel
  312.  * 1.  Corrected a typo in the comments.
  313.  * 
  314.  * Revision 1.4  90/07/03  14:20:23  vogel
  315.  * 1.  Copied the desired file extension into the MACRO structure.
  316.  * 
  317.  * Revision 1.3  90/07/03  12:05:23  vogel
  318.  * 1.  Added "nextfile" variable, to hold the next file to be created.
  319.  * 2.  Got rid of debugging print statements for the macros structure.
  320.  * 3.  Added code to create and optionally edit each file in turn.
  321.  * 
  322.  * Revision 1.2  90/06/29  17:40:04  vogel
  323.  * 1.  Added header file and definitions for the macro substitution strings.
  324.  * 2.  Added code to print help if needed.
  325.  * 
  326.  * Revision 1.1  90/06/29  15:27:52  vogel
  327.  * Initial revision
  328.  * 
  329.  */
  330.  
  331. #include    "new.h"
  332. #include    "macro.h"
  333. #include    <strings.h>
  334. #include    <sys/param.h>
  335.  
  336. main (argc, argv)
  337. int             argc;
  338. char          **argv;
  339. {
  340.  
  341. /*
  342.  *    Variables.
  343.  */
  344.  
  345.     MACRO          *macros;
  346.     MACRO           macbuffer;
  347.  
  348.     OPTIONS        *options;
  349.     OPTIONS         opbuffer;
  350.  
  351.     char            nextfile[MAXPATHLEN];
  352.  
  353.     int             k;
  354.     int             status;
  355.  
  356. /*
  357.  *    Process the command line options.  If they are not OK, offer some
  358.  *    help and exit.
  359.  */
  360.  
  361.     options = &opbuffer;
  362.     status = GetOptions (argc, argv, options);
  363.  
  364.     if (status == EMALLOC)
  365.     {
  366.         fprintf (stderr, "Severe memory error -- please call the ");
  367.         fprintf (stderr, "System Administrator.\n");
  368.         exit (1);
  369.     }
  370.  
  371.     if (options->help)
  372.     {
  373.         (void) Help ();
  374.         exit (1);
  375.     }
  376.  
  377. /*
  378.  *    Set up the substitution macros.
  379.  */
  380.  
  381.     macros = &macbuffer;
  382.     SetMacros (macros);
  383.     (void) strcpy (macros->exten, options->exten);
  384.  
  385. /*
  386.  *    Create and optionally edit each file in turn.
  387.  */
  388.  
  389.     for (k = 0; options->files[k]; ++k)
  390.     {
  391.         (void) strcpy (nextfile, options->files[k]);
  392.  
  393.         if (CreateCode (macros, options->template, nextfile) == 0)
  394.             if (options->edit)
  395.                 EditCode (nextfile);
  396.     }
  397.  
  398.     exit (0);
  399. }
  400.  
  401. ==============================================================================
  402.  
  403.             Listing 4.  File "CreateCode.c"
  404.  
  405. #ifndef    lint
  406. static char    *CreateCode_c_rcsid =
  407. "$Header: CreateCode.c,v 1.2 91/03/15 16:55:25 vogel Exp $";
  408.  
  409. static char    *CreateCode_c_source =
  410. "$Source: /d/cdc/vogel/source/new/RCS/CreateCode.c,v $";
  411.  
  412. #endif
  413.  
  414. /*
  415.  * NAME:
  416.  *    CreateCode
  417.  *
  418.  * SYNOPSIS:
  419.  *    #include "macro.h"
  420.  *
  421.  *    int CreateCode (macros, template, nextfile)
  422.  *    MACRO * macros;
  423.  *    char * template;
  424.  *    char * nextfile;
  425.  *
  426.  * DESCRIPTION:
  427.  *    Accepts the substitution structure, the input file, and the new C
  428.  *    file to be created.  Reads the template file, fills it in with the
  429.  *    contents of the substitution structure, and writes the results to
  430.  *    the new C file.
  431.  *
  432.  *    A function value of 0 is returned if everything is OK.
  433.  *    A function value of 1 is returned if the template could not be read.
  434.  *    A function value of 2 is returned if the output could not be written.
  435.  *
  436.  * ARGUMENTS:
  437.  *    "macros" is the structure holding the macro substitution values.
  438.  *    "template" is the name of the input template file.
  439.  *    "nextfile" is the name of the next output file.
  440.  *
  441.  * AUTHOR:
  442.  *    Karl Vogel
  443.  *
  444.  * BUGS:
  445.  *    None noticed.
  446.  *
  447.  * REVISIONS:
  448.  *
  449.  * $Log:    CreateCode.c,v $
  450.  * Revision 1.2  91/03/15  16:55:25  vogel
  451.  * 1.  Ran indent on the code and reformatted the comment header.
  452.  * 
  453.  * Revision 1.1  90/07/03  11:59:45  vogel
  454.  * Initial revision
  455.  * 
  456.  */
  457.  
  458. #include    "macro.h"
  459. #include    <stdio.h>
  460. #include    <strings.h>
  461. #include    <sys/file.h>
  462.  
  463. #define        SMALLBUF    20
  464.  
  465. int             CreateCode (macros, template, nextfile)
  466. MACRO          *macros;
  467. char           *template;
  468. char           *nextfile;
  469. {
  470.  
  471. /*
  472.  *    Variables.
  473.  */
  474.  
  475.     FILE           *in;
  476.     FILE           *out;
  477.  
  478.     char           *base;
  479.     char           *dot;
  480.     char            last[SMALLBUF];
  481.     char            prompt[SMALLBUF];
  482.  
  483.     int             length;
  484.     int             status;
  485.  
  486. /*
  487.  *    If the filename already has the default extension specified in the
  488.  *    MACRO structure, zap it so we can store the function name in the
  489.  *    MACRO structure.
  490.  */
  491.  
  492.     status = 0;
  493.     in = (FILE *) NULL;
  494.     out = (FILE *) NULL;
  495.  
  496.     last[0] = '.';
  497.     last[1] = '\0';
  498.  
  499.     (void) strcat (last, macros->exten);
  500.     length = strlen (last);
  501.  
  502.     if (dot = rindex (nextfile, '.'))
  503.         if (strcmp (dot, last) == 0)
  504.             *dot = '\0';
  505.  
  506.     if (base = rindex (nextfile, '/'))
  507.         base++;
  508.     else
  509.         base = nextfile;
  510.  
  511.     (void) strcpy (macros->name, base);
  512.     (void) strcat (nextfile, last);
  513.  
  514. /*
  515.  *    If the output file already exists, make sure that the user wants
  516.  *    to overwrite it.
  517.  */
  518.  
  519.     if (access (nextfile, F_OK) == 0)
  520.     {
  521.         printf ("File \"%s\" exists.  Overwrite?  ", nextfile);
  522.         fflush (stdout);
  523.         fgets (prompt, SMALLBUF, stdin);
  524.  
  525.         if (prompt[0] != 'y' && prompt[0] != 'Y')
  526.         {
  527.             printf ("\"%s\" not overwritten.\n", nextfile);
  528.             goto done;
  529.         }
  530.     }
  531.  
  532. /*
  533.  *    Open the input template file.
  534.  */
  535.  
  536.     if ((in = fopen (template, "r")) == (FILE *) NULL)
  537.     {
  538.         printf ("Unable to open template file \"%s\"\n", template);
  539.         status = 1;
  540.         goto done;
  541.     }
  542.  
  543. /*
  544.  *    Open the output C file.
  545.  */
  546.  
  547.     if ((out = fopen (nextfile, "w")) == (FILE *) NULL)
  548.     {
  549.         printf ("Unable to open C file \"%s\"\n", nextfile);
  550.         status = 2;
  551.         goto done;
  552.     }
  553.  
  554. /*
  555.  *    Do the macro substitution, clean up, and return.
  556.  */
  557.  
  558.     ReplaceMacros (in, macros, out);
  559.  
  560. done:
  561.     if (in)
  562.         (void) fclose (in);
  563.  
  564.     if (out)
  565.         (void) fclose (out);
  566.  
  567.     return (status);
  568. }
  569.  
  570. ==============================================================================
  571.  
  572.             Listing 5.  File "EditCode.c"
  573.  
  574. #ifndef    lint
  575. static char    *EditCode_c_rcsid =
  576. "$Header: EditCode.c,v 1.2 91/03/15 16:55:28 vogel Exp $";
  577.  
  578. static char    *EditCode_c_source =
  579. "$Source: /d/cdc/vogel/source/new/RCS/EditCode.c,v $";
  580.  
  581. #endif
  582.  
  583. /*
  584.  * NAME:
  585.  *    EditCode
  586.  *
  587.  * SYNOPSIS:
  588.  *    int EditCode (nextfile)
  589.  *    char * nextfile;
  590.  *
  591.  * DESCRIPTION:
  592.  *    Edits the new C file using either "cvi" or whatever the user has in
  593.  *    his "EDITOR" environment variable.
  594.  *
  595.  * ARGUMENTS:
  596.  *    "nextfile" is the new C file.
  597.  *
  598.  * AUTHOR:
  599.  *    Karl Vogel
  600.  *
  601.  * BUGS:
  602.  *    None noticed.
  603.  *
  604.  * REVISIONS:
  605.  *
  606.  * $Log:    EditCode.c,v $
  607.  * Revision 1.2  91/03/15  16:55:28  vogel
  608.  * 1.  Ran indent on the code and reformatted the comment header.
  609.  * 
  610.  * Revision 1.1  90/07/03  12:00:13  vogel
  611.  * Initial revision
  612.  */
  613.  
  614. #include    <stdio.h>
  615.  
  616. int             EditCode (nextfile)
  617. char           *nextfile;
  618. {
  619.  
  620. /*
  621.  *    Functions.
  622.  */
  623.  
  624.     char           *getenv ();
  625.  
  626. /*
  627.  *    Variables.
  628.  */
  629.  
  630.     char           *editor;
  631.     char            cmd[BUFSIZ];
  632.  
  633.     int             status;
  634.  
  635. /*
  636.  *    Create and execute the edit command.
  637.  */
  638.  
  639.     if (editor = getenv ("EDITOR"))
  640.         (void) strcpy (cmd, editor);
  641.     else
  642.         (void) strcpy (cmd, "cvi");
  643.  
  644.     (void) strcat (cmd, " ");
  645.     (void) strcat (cmd, nextfile);
  646.     (void) system (cmd);
  647.  
  648.     return (0);
  649. }
  650.  
  651. ==============================================================================
  652.  
  653.             Listing 6.  File "GetOptions.c"
  654.  
  655. #ifndef    lint
  656. static char    *GetOptions_c_rcsid =
  657. "$Header: GetOptions.c,v 1.4 91/03/15 16:55:31 vogel Exp $";
  658.  
  659. static char    *GetOptions_c_source =
  660. "$Source: /d/cdc/vogel/source/new/RCS/GetOptions.c,v $";
  661.  
  662. #endif
  663.  
  664. /*
  665.  * NAME:
  666.  *    GetOptions
  667.  *
  668.  * SYNOPSIS:
  669.  *    #include "new.h"
  670.  *
  671.  *    int GetOptions (argc, argv, options)
  672.  *    int argc;
  673.  *    char ** argv;
  674.  *    OPTIONS * options;
  675.  *
  676.  * DESCRIPTION:
  677.  *    Accepts the command line arguments and a pointer to a structure which
  678.  *    holds the options, and parses the arguments into the structure.
  679.  *
  680.  * ARGUMENTS:
  681.  *    "argc" and "argv" are the normal C program variables holding the
  682.  *    argument list.
  683.  *
  684.  *    "options" is the structure meant to hold the options.
  685.  *
  686.  * AUTHOR:
  687.  *    Karl Vogel
  688.  *
  689.  * BUGS:
  690.  *    Any problems or suggestions. 
  691.  *
  692.  * REVISIONS:
  693.  *
  694.  * $Log:    GetOptions.c,v $
  695.  * Revision 1.4  91/03/15  16:55:31  vogel
  696.  * 1.  Ran indent on the code and reformatted the comment header.
  697.  * 
  698.  * Revision 1.3  90/07/03  14:19:49  vogel
  699.  * 1.  Added code to set up the file extension based on the command line options.
  700.  *     "new -mh" gives you a file with name ending in ".h", anything else gives
  701.  *     you a file with name ending in ".c".
  702.  * 
  703.  * Revision 1.2  90/07/03  12:01:01  vogel
  704.  * 1.  Added new option '-c'.
  705.  * 2.  Added code to make sure that default template is properly set up.
  706.  * 
  707.  * Revision 1.1  90/06/29  15:28:13  vogel
  708.  * Initial revision
  709.  * 
  710.  */
  711.  
  712. #include    "new.h"
  713. #include    <strings.h>
  714.  
  715. #define        SMALL        10
  716.  
  717. int             GetOptions (argc, argv, options)
  718. int             argc;
  719. char          **argv;
  720. OPTIONS        *options;
  721. {
  722.  
  723. /*
  724.  *    Functions.
  725.  */
  726.  
  727.     char           *malloc ();
  728.  
  729. /*
  730.  *    Variables.
  731.  */
  732.  
  733.     char           *next;
  734.     char            extension[SMALL + 1];
  735.  
  736.     int             count;
  737.     int             flags;
  738.     int             k;
  739.     int             status;
  740.  
  741.     unsigned int    length;
  742.  
  743. /*
  744.  *    Initialize options to defaults.
  745.  */
  746.  
  747.     options->files = (char **) NULL;
  748.     options->template = (char *) NULL;
  749.     options->edit = YES;
  750.     options->help = NO;
  751.  
  752.     (void) strcpy (extension, "f");
  753.  
  754.     count = 0;
  755.     status = OK;
  756.  
  757. /*
  758.  *    Handle the flags, and count the files.
  759.  */
  760.  
  761.     for (k = 1; k < argc; ++k)
  762.     {
  763.         next = argv[k];
  764.  
  765.         if (*next == '-')
  766.         {
  767.             next++;
  768.  
  769.             if (*next == 'm')
  770.             {
  771.                 (void) strncpy (extension, next + 1, SMALL);
  772.                 extension[SMALL] = '\0';
  773.             }
  774.  
  775.             else
  776.             if (*next == 'c')
  777.                 options->edit = NO;
  778.  
  779.             else
  780.             {
  781.                 options->help = YES;
  782.                 goto done;
  783.             }
  784.         }
  785.  
  786.         else            /* option does not start with a dash  */
  787.             count++;
  788.     }
  789.  
  790. /*
  791.  *    If no files were specified, set the help flag.  Otherwise, store
  792.  *    the filenames.
  793.  */
  794.  
  795.     if (count)
  796.     {
  797.         length = (unsigned) ((count + 1) * (sizeof (char *)));
  798.  
  799.         if (options->files = (char **) malloc (length))
  800.         {
  801.             for (k = 1, count = 0; k < argc; ++k)
  802.                 if (*argv[k] != '-')
  803.                     options->files[count++] = argv[k];
  804.  
  805.             options->files[count] = (char *) NULL;
  806.         }
  807.         else
  808.         {
  809.             status = EMALLOC;
  810.             goto done;
  811.         }
  812.     }
  813.     else
  814.     {
  815.         options->help = YES;
  816.         goto done;
  817.     }
  818.  
  819. /*
  820.  *    Set up the file extension.
  821.  */
  822.  
  823.     if (strcmp (extension, "h") == 0)
  824.         options->exten[0] = 'h';
  825.     else
  826.         options->exten[0] = 'c';
  827.  
  828.     options->exten[1] = '\0';
  829.  
  830. /*
  831.  *    Set up the template pathname.
  832.  */
  833.  
  834.     length = (unsigned) (strlen (DIRECTORY) + strlen (PREFIX) +
  835.                  strlen (extension) + 1);
  836.  
  837.     if (options->template = malloc (length))
  838.         (void) sprintf (options->template, "%s%s%s", DIRECTORY,
  839.                 PREFIX, extension);
  840.     else
  841.         status = EMALLOC;
  842.  
  843. done:
  844.     return (status);
  845. }
  846.  
  847. ==============================================================================
  848.  
  849.             Listing 7.  File "Help.c"
  850.  
  851. #ifndef    lint
  852. static char    *Help_c_rcsid =
  853. "$Header: Help.c,v 1.4 91/03/15 16:55:33 vogel Exp $";
  854.  
  855. static char    *Help_c_source =
  856. "$Source: /d/cdc/vogel/source/new/RCS/Help.c,v $";
  857.  
  858. #endif
  859.  
  860. /*
  861.  * NAME:
  862.  *    Help
  863.  *
  864.  * SYNOPSIS:
  865.  *    int Help ()
  866.  *
  867.  * DESCRIPTION:
  868.  *    Prints help information to stdout.
  869.  *
  870.  * ARGUMENTS:
  871.  *    None.
  872.  *
  873.  * AUTHOR:
  874.  *    Karl Vogel
  875.  *
  876.  * BUGS:
  877.  *    None noticed.
  878.  *
  879.  * REVISIONS:
  880.  *
  881.  * $Log:    Help.c,v $
  882.  * Revision 1.4  91/03/15  16:55:33  vogel
  883.  * 1.  Ran indent on the code and reformatted the comment header.
  884.  * 
  885.  * Revision 1.3  90/09/24  16:40:47  vogel
  886.  * 1.  Corrected a typo.
  887.  * 
  888.  * Revision 1.2  90/07/03  12:01:42  vogel
  889.  * 1.  Changed print strings to reflect new '-c' option.
  890.  * 
  891.  * Revision 1.1  90/06/29  17:40:46  vogel
  892.  * Initial revision
  893.  * 
  894.  */
  895.  
  896. #include    <stdio.h>
  897.  
  898. int             Help ()
  899. {
  900.  
  901. /*
  902.  *    Variables.
  903.  */
  904.  
  905.     int             k;
  906.  
  907.     static char    *array[] =
  908.     {
  909.      "",
  910.      "\tnew:\t\tcreates and optionally edits one or more new C",
  911.      "\t\t\tprograms.",
  912.      "",
  913.      "\t\tUsage:\tnew [-c] [-h] [-mx] file [file ...]",
  914.      "",
  915.      "\t\tWhere:\t\"-c\"\tcreates a new program but does NOT edit it.",
  916.      "",
  917.      "\t\t\t\"-h\"\tprints a help file.  Help is also given if",
  918.      "\t\t\t\tno arguments at all are given.",
  919.      "",
  920.      "\t\t\t\"-mx\"\tcreates a program of type 'x', where x is",
  921.      "\t\t\t\tone of the following:",
  922.      "\t",
  923.      "\t\t\t\td - function driver.",
  924.      "\t\t\t\tf - normal function (default).",
  925.      "\t\t\t\th - header file.",
  926.      "\t\t\t\ti - program to handle simple I/O.",
  927.      "\t\t\t\tm - main routine with arguments.",
  928.      "\t\t\t\to - function to handle command line arguments.",
  929.      "\t\t\t\ts - stub (placeholder) function.",
  930.      "",
  931.      "\t\t\t\"file\"\tis one or more C files to be created.  A",
  932.      "\t\t\t\tsuffix of \".c\" will be appended if it isn't",
  933.      "\t\t\t\tthere already.",
  934.      "\t",
  935.      "\t\t\t\tIf the file already exists, you will be asked",
  936.      "\t\t\t\tif you want to overwrite it.",
  937.      "",
  938.      "",
  939.      "\t\t\"new\" makes extensive use of templates to create new C files.",
  940.      "\t\tA template file has the name \"template.x\", where 'x' is the",
  941.      "\t\tstring which follows '-m' in the program arguments.",
  942.      "\t",
  943.      "\t\tYou can create other templates by adding template files to",
  944.     "\t\tthe template directory specified in the header file \"new.h\".",
  945.      (char *) NULL
  946.     };
  947.  
  948. /*
  949.  *    Write the help information.
  950.  */
  951.  
  952.     for (k = 0; array[k]; ++k)
  953.         puts (array[k]);
  954.  
  955.     return (0);
  956. }
  957.  
  958. ==============================================================================
  959.  
  960.             Listing 8.  File "OutString.c"
  961.  
  962. #ifndef    lint
  963. static char    *OutString_c_rcsid =
  964. "$Header: OutString.c,v 1.2 91/03/15 16:55:35 vogel Exp $";
  965.  
  966. static char    *OutString_c_source =
  967. "$Source: /d/cdc/vogel/source/new/RCS/OutString.c,v $";
  968.  
  969. #endif
  970.  
  971. /*
  972.  * NAME:
  973.  *    OutString
  974.  *
  975.  * SYNOPSIS:
  976.  *    #include "new.h"
  977.  *    #include "macro.h"
  978.  *
  979.  *    int OutString (macros, current, string)
  980.  *    MACRO * macros;
  981.  *    char current;
  982.  *    char * string;
  983.  *
  984.  * DESCRIPTION:
  985.  *    Decides which macro string to return based on the current token
  986.  *    character.
  987.  *    
  988.  *
  989.  * ARGUMENTS:
  990.  *    "macros" holds the current macro replacement values.
  991.  *
  992.  *    "current" is the value of the token character following a dollar sign.
  993.  *
  994.  *    "string" is the replacement value of that token.
  995.  *
  996.  * AUTHOR:
  997.  *    Karl Vogel
  998.  *
  999.  * BUGS:
  1000.  *    None noticed.
  1001.  *
  1002.  * REVISIONS:
  1003.  *
  1004.  * $Log:    OutString.c,v $
  1005.  * Revision 1.2  91/03/15  16:55:35  vogel
  1006.  * 1.  Ran indent on the code and reformatted the comment header.
  1007.  * 
  1008.  * Revision 1.1  90/07/03  12:02:28  vogel
  1009.  * Initial revision
  1010.  * 
  1011.  */
  1012.  
  1013. #include    "new.h"
  1014. #include    "macro.h"
  1015. #include    <stdio.h>
  1016. #include    <ctype.h>
  1017. #include    <strings.h>
  1018.  
  1019. int             OutString (macros, current, string)
  1020. MACRO          *macros;
  1021. char            current;
  1022. char           *string;
  1023. {
  1024.  
  1025. /*
  1026.  *    Variables.
  1027.  */
  1028.  
  1029.     char           *blank;
  1030.     char           *s;
  1031.     char           *t;
  1032.     char            temp[BUFFER];
  1033.  
  1034.     int             col;
  1035.     int             first;
  1036.     int             length;
  1037.     int             status;
  1038.  
  1039. /*
  1040.  *    Do the simple string replacements, and numeric conversion.
  1041.  */
  1042.  
  1043.     switch (current)
  1044.     {
  1045.         case 'a':
  1046.             (void) strcpy (string, macros->args);
  1047.             break;
  1048.  
  1049.         case 'b':
  1050.             (void) strcpy (string, macros->body);
  1051.             break;
  1052.  
  1053.         case 'c':
  1054.             (void) sprintf (string, "%2.2d", macros->month);
  1055.             break;
  1056.  
  1057.         case 'd':
  1058.             (void) sprintf (string, "%2.2d", macros->day);
  1059.             break;
  1060.  
  1061.         case 'e':
  1062.             (void) strcpy (string, macros->exten);
  1063.             break;
  1064.  
  1065.         case 'f':
  1066.             (void) strcpy (string, macros->functions);
  1067.             break;
  1068.  
  1069.         case 'g':
  1070.             (void) strcpy (string, macros->globals);
  1071.             break;
  1072.  
  1073.         case 'h':
  1074.             (void) sprintf (string, "%2.2d", macros->hour);
  1075.             break;
  1076.  
  1077.         case 'i':
  1078.             break;
  1079.  
  1080.         case 'l':
  1081.             (void) strcpy (string, macros->alist);
  1082.             break;
  1083.  
  1084.         case 'm':
  1085.             (void) sprintf (string, "%2.2d", macros->minute);
  1086.             break;
  1087.  
  1088.         case 'n':
  1089.             (void) strcpy (string, macros->name);
  1090.             break;
  1091.  
  1092.         case 'p':
  1093.             (void) strcpy (string, macros->define);
  1094.             break;
  1095.  
  1096.         case 'r':
  1097.             (void) strcpy (string, macros->rev);
  1098.             break;
  1099.  
  1100.         case 's':
  1101.             (void) sprintf (string, "%2.2d", macros->second);
  1102.             break;
  1103.  
  1104.         case 't':
  1105.             (void) strcpy (string, macros->type);
  1106.             break;
  1107.  
  1108.         case 'u':
  1109.             break;
  1110.  
  1111.         case 'v':
  1112.             (void) strcpy (string, macros->vars);
  1113.             break;
  1114.  
  1115.         case 'w':
  1116.             (void) strcpy (string, macros->userid);
  1117.             break;
  1118.  
  1119.         case 'x':
  1120.             (void) strcpy (string, macros->username);
  1121.             break;
  1122.  
  1123.         case 'y':
  1124.             (void) sprintf (string, "%2.2d", macros->year);
  1125.             break;
  1126.  
  1127.         default:
  1128.             *string = '\0';
  1129.             break;
  1130.     }
  1131.  
  1132. /*
  1133.  *    Handle the "Usage" string.  Write no more than 50 characters per
  1134.  *    line, indented 3 tab spaces in.
  1135.  */
  1136.  
  1137.     if (current == 'u')
  1138.     {
  1139.         (void) strcpy (temp, macros->usage);
  1140.         t = temp;
  1141.  
  1142.         *string = '\0';
  1143.         first = YES;
  1144.  
  1145.         while (length = strlen (t))
  1146.         {
  1147.             if (!first)
  1148.                 (void) strcat (string, "\n * \t\t\t");
  1149.  
  1150.             first = NO;
  1151.  
  1152.             if (length <= 50)
  1153.             {
  1154.                 (void) strcat (string, t);
  1155.                 break;
  1156.             }
  1157.  
  1158.             else
  1159.             {
  1160.                 blank = (char *) NULL;
  1161.                 col = 25;
  1162.  
  1163.                 for (s = t; *s && col < 75; ++s, ++col)
  1164.                     if (isspace (*s))
  1165.                         blank = s;
  1166.  
  1167.                 if (blank)
  1168.                 {
  1169.                     *blank = '\0';
  1170.                     (void) strcat (string, t);
  1171.                     t = blank + 1;
  1172.                 }
  1173.                 else
  1174.                 {
  1175.                     (void) strcat (string, t);
  1176.                     break;
  1177.                 }
  1178.             }
  1179.         }
  1180.     }
  1181.  
  1182. /*
  1183.  *    Handle the "include" strings.
  1184.  */
  1185.  
  1186.     if (current == 'i')
  1187.     {
  1188.         for (s = string, t = macros->include; *t; ++s, ++t)
  1189.         {
  1190.             if (*t == ' ')
  1191.                 *s = '\t';
  1192.             else
  1193.                 *s = *t;
  1194.         }
  1195.  
  1196.         *s = '\0';
  1197.     }
  1198.  
  1199.     return (0);
  1200. }
  1201.  
  1202. ==============================================================================
  1203.  
  1204.             Listing 9.  File "ReplaceMacros.c"
  1205.  
  1206. #ifndef    lint
  1207. static char    *ReplaceMacros_c_rcsid =
  1208. "$Header: ReplaceMacros.c,v 1.2 91/03/15 16:55:37 vogel Exp $";
  1209.  
  1210. static char    *ReplaceMacros_c_source =
  1211. "$Source: /d/cdc/vogel/source/new/RCS/ReplaceMacros.c,v $";
  1212.  
  1213. #endif
  1214.  
  1215. /*
  1216.  * NAME:
  1217.  *    ReplaceMacros
  1218.  *
  1219.  * SYNOPSIS:
  1220.  *    #include "macro.h"
  1221.  *
  1222.  *    int ReplaceMacros (in, macros, out)
  1223.  *    FILE * in;
  1224.  *    MACRO * macros;
  1225.  *    FILE * out;
  1226.  *
  1227.  * DESCRIPTION:
  1228.  *    Accepts the macro structure holding the variables to be replaced,
  1229.  *    an input filepointer, and an output filepointer.  Does token
  1230.  *    substitution from input to output.
  1231.  *
  1232.  * ARGUMENTS:
  1233.  *    Described above.
  1234.  *
  1235.  * AUTHOR:
  1236.  *    Karl Vogel
  1237.  *
  1238.  * BUGS:
  1239.  *    None noticed.
  1240.  *
  1241.  * REVISIONS:
  1242.  *
  1243.  * $Log:    ReplaceMacros.c,v $
  1244.  * Revision 1.2  91/03/15  16:55:37  vogel
  1245.  * 1.  Ran indent on the code and reformatted the comment header.
  1246.  * 
  1247.  * Revision 1.1  90/07/03  12:02:42  vogel
  1248.  * Initial revision
  1249.  * 
  1250.  */
  1251.  
  1252. #include    "macro.h"
  1253. #include    <stdio.h>
  1254. #include    <ctype.h>
  1255. #include    <strings.h>
  1256.  
  1257. int             ReplaceMacros (in, macros, out)
  1258. FILE           *in;
  1259. MACRO          *macros;
  1260. FILE           *out;
  1261. {
  1262.  
  1263. /*
  1264.  *    Variables.
  1265.  */
  1266.  
  1267.     char           *s;
  1268.     char            string[BUFFER];
  1269.     char            current;
  1270.     char            previous;
  1271.  
  1272. /*
  1273.  *    Start the main loop which looks ahead one character.
  1274.  */
  1275.  
  1276.     previous = getc (in);
  1277.  
  1278.     if (previous == EOF)
  1279.         return (0);
  1280.  
  1281. /*
  1282.  *    Decide what to do if we get a token character.
  1283.  */
  1284.  
  1285.     while ((current = getc (in)) != EOF)
  1286.     {
  1287.         if (previous == macros->token)
  1288.         {
  1289.             if (index ("abcdefghilmnprstuvwxy", current))
  1290.             {
  1291.                 OutString (macros, current, string);
  1292.  
  1293.                 for (s = string; *s; ++s)
  1294.                     putc (*s, out);
  1295.  
  1296.                 previous = getc (in);
  1297.             }
  1298.             else
  1299.             {
  1300.                 putc (previous, out);
  1301.                 previous = current;
  1302.             }
  1303.         }
  1304.         else
  1305.         {
  1306.             putc (previous, out);
  1307.             previous = current;
  1308.         }
  1309.     }
  1310.  
  1311. /*
  1312.  *    Don't forget to write the last character.
  1313.  */
  1314.  
  1315.     putc (previous, out);
  1316.     return (0);
  1317. }
  1318.  
  1319. ==============================================================================
  1320.  
  1321.             Listing 10.  File "SetMacros.c"
  1322.  
  1323. #ifndef    lint
  1324. static char    *SetMacros_c_rcsid =
  1325. "$Header: SetMacros.c,v 1.4 91/03/15 16:55:40 vogel Exp $";
  1326.  
  1327. static char    *SetMacros_c_source =
  1328. "$Source: /d/cdc/vogel/source/new/RCS/SetMacros.c,v $";
  1329.  
  1330. #endif
  1331.  
  1332. /*
  1333.  * NAME:
  1334.  *    SetMacros
  1335.  *
  1336.  * SYNOPSIS:
  1337.  *    #include "macro.h"
  1338.  *
  1339.  *    int SetMacros (macros)
  1340.  *    MACRO * macros;
  1341.  *
  1342.  * DESCRIPTION:
  1343.  *    Sets up the MACRO structure used for token replacement.
  1344.  *    
  1345.  * ARGUMENTS:
  1346.  *    Described above.
  1347.  *
  1348.  * AUTHOR:
  1349.  *    Karl Vogel
  1350.  *
  1351.  * BUGS:
  1352.  *    None noticed.
  1353.  *
  1354.  * REVISIONS:
  1355.  *
  1356.  * $Log:    SetMacros.c,v $
  1357.  * Revision 1.4  91/03/15  16:55:40  vogel
  1358.  * 1.  Ran indent on the code and reformatted the comment header.
  1359.  * 
  1360.  * Revision 1.3  90/09/24  16:41:39  vogel
  1361.  * 1.  Corrected an off-by-one error in the month.  Unix stores the month as a
  1362.  *     digit from 0 to 11 instead of 1 to 12.
  1363.  * 
  1364.  * Revision 1.2  90/07/03  12:03:48  vogel
  1365.  * 1.  Function type no longer has to end with a tab.
  1366.  * 2.  Preprocessor "include" commands no longer have to have internal tabs.
  1367.  * 
  1368.  * Revision 1.1  90/06/29  17:40:53  vogel
  1369.  * Initial revision
  1370.  * 
  1371.  */
  1372.  
  1373. #include    "macro.h"
  1374. #include    <stdio.h>
  1375. #include    <strings.h>
  1376. #include    <pwd.h>
  1377. #include    <sys/time.h>
  1378.  
  1379. int             SetMacros (macros)
  1380. MACRO          *macros;
  1381. {
  1382.  
  1383. /*
  1384.  *    Functions.
  1385.  */
  1386.  
  1387.     char           *getenv ();
  1388.  
  1389.     struct passwd  *getpwuid ();
  1390.  
  1391. /*
  1392.  *    Variables.
  1393.  */
  1394.  
  1395.     char           *s;
  1396.  
  1397.     int             offset;
  1398.  
  1399.     long            clock;
  1400.  
  1401.     struct passwd  *ptr;
  1402.  
  1403.     struct tm      *now;
  1404.  
  1405. /*
  1406.  *    Set up the internal C stuff.  The "name" entry will be set later.
  1407.  */
  1408.  
  1409.     macros->args[0] = '\0';
  1410.     macros->body[0] = '\0';
  1411.     macros->functions[0] = '\0';
  1412.     macros->globals[0] = '\0';
  1413.     macros->alist[0] = '\0';
  1414.     macros->name[0] = '\0';
  1415.     macros->define[0] = '\0';
  1416.     macros->usage[0] = '\0';
  1417.     macros->vars[0] = '\0';
  1418.  
  1419.     (void) strcpy (macros->exten, "c");
  1420.     (void) strcpy (macros->rev, "1.1");
  1421.     (void) strcpy (macros->type, "int");
  1422.  
  1423.     (void) strcpy (macros->include,
  1424.                "#include <stdio.h>\n#include <ctype.h>");
  1425.  
  1426. /*
  1427.  *    Set up the userid and full name of the program author.  See if we
  1428.  *    can get the information from the environment, and if that fails,
  1429.  *    look it up from the userid and the passwd file.
  1430.  */
  1431.  
  1432.     macros->userid[0] = '\0';
  1433.     macros->username[0] = '\0';
  1434.  
  1435.     if (s = getenv ("USER"))
  1436.         (void) strcpy (macros->userid, s);
  1437.  
  1438.     if (s = getenv ("USERNAME"))
  1439.         (void) strcpy (macros->username, s);
  1440.  
  1441.     if (strlen (macros->userid) == 0 || strlen (macros->username) == 0)
  1442.     {
  1443.         if (ptr = getpwuid (getuid ()))
  1444.         {
  1445.             (void) strcpy (macros->userid, ptr->pw_name);
  1446.  
  1447.             if (strncmp (ptr->pw_gecos, "Civ ", 4) == 0)
  1448.                 offset = 4;
  1449.             else
  1450.                 offset = 0;
  1451.  
  1452.             (void) strcpy (macros->username,
  1453.                        ptr->pw_gecos + offset);
  1454.  
  1455.             if (s = index (macros->username, ';'))
  1456.                 *s = '\0';
  1457.         }
  1458.         else
  1459.         {
  1460.             (void) strcpy (macros->userid, "unknown");
  1461.             (void) strcpy (macros->username, "unknown");
  1462.         }
  1463.     }
  1464.  
  1465. /*
  1466.  *    Set the character which we will recognize as the start of a token.
  1467.  */
  1468.  
  1469.     macros->token = '$';
  1470.  
  1471. /*
  1472.  *    Set up the current date and time.
  1473.  */
  1474.  
  1475.     (void) time (&clock);
  1476.     now = localtime (&clock);
  1477.  
  1478.     macros->second = now->tm_sec;
  1479.     macros->minute = now->tm_min;
  1480.     macros->hour = now->tm_hour;
  1481.     macros->day = now->tm_mday;
  1482.     macros->month = now->tm_mon + 1;
  1483.     macros->year = now->tm_year;
  1484.  
  1485.     return (0);
  1486. }
  1487.  
  1488.